/*----------------------------------------------------------------------
 *
 *  Copyright 2007, Thomas Dejanovic.
 *
 *  This is free software; you can redistribute it and/or modify it
 *  under the terms of the GNU Lesser General Public License as
 *  published by the Free Software Foundation; either version 2.1 of
 *  the License, or (at your option) any later version.
 *
 *  This software is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 *  Lesser General Public License for more details.
 *
 *  You should have received a copy of the GNU Lesser General Public
 *  License along with this software; if not, write to the Free
 *  Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 *  02110-1301 USA, or see the FSF site: http://www.fsf.org.
 *
 *----------------------------------------------------------------------
 *
 *  apb bus tasks for test benches.
 *
 *  this assumes an apb bus that looks a bit like this exists:
 *
 *   input              pclk;
 *   input              pclk_en;
 *   input              gated_pclk;
 *   input              gated_pclk_en;
 *   input              preset_l;
 *   input              penable;
 *   input              psel;
 *   input              pwrite;
 *   input  [31:0]      pwdata;
 *   output [31:0]      prdata;
 *   input  [9:2]       paddr;
 *
 *
 *    APB Interface Timing.
 *                 ___     ___     ___
 *    clk      ___/   \___/   \___/   \___
 *                          _______
 *    penable  ____________/       \______
 *                  _______________
 *    psel     ____/               \______
 *                  _______________
 *    paddr    XXXXX_______________XXXXXXX
 *                  _______________
 *    pwdata   XXXXX_______________XXXXXXX
 *                          _______
 *    prdata   XXXXXXXXXXXXX_______XXXXXXX
 *
 *----------------------------------------------------------------------
 *  id = $Id: apb_bus_tasks.v 667 2010-07-01 00:12:17Z jayshurtz $
 *  $URL: http://hatch.googlecode.com/svn/tags/taggle_release_3.0/test/old_tests/rtl/apb_bus_tasks.v $
 *  $Author: jayshurtz $
 *---------------------------------------------------------------------*/

  // very simple 100Mhz Clock.
  reg pclk100;
  initial pclk100 = 0;
  always #5 pclk100 = ~pclk100;


  reg  enable_gated_pclk;
  initial enable_gated_pclk = 1;

  // clock setup.
  assign pclk    = pclk100;
  assign pclk_en = 1'd1;

`ifdef USE_GATED_CLOCKS
  assign gated_pclk    = enable_gated_pclk ? pclk100 : 1'd0;
  assign gated_pclk_en = 1'd1;
`else
  assign gated_pclk    = pclk100;
  assign gated_pclk_en = enable_gated_pclk;
`endif

  // simple reset setup.
  initial begin
    preset_l = 0;

    // deassert reset after 4 clock cycles.
    @ (posedge pclk);
    @ (posedge pclk);
    @ (posedge pclk);

    // define the bus inputs about now.
    penable = 1'd0;
    psel    = 1'd0;
    pwrite  = 1'd0;
    pwdata  = 32'd0;
    paddr   = 8'd0;

    @ (posedge pclk);

    preset_l = 1;
    enable_gated_pclk = 0;
  end


  /*------------------------------------------------------------------
   *
   * apb write.
   *
   * */

  task apb_write;

    // Arguments:
    input [31:0] address;
    input [31:0] data;

    begin
`ifdef DEBUG
      $display("APB write to addr: %x, data: %x : %m", address, data);
`endif
      // assume we have been called on or soon after the rising edge of pclk.
      // #1;
      enable_gated_pclk <= 1;
      penable <= 0;
      psel    <= 1;
      pwrite  <= 1'd1;
      pwdata  <= data;
      paddr   <= address[9:2];

      @ (posedge pclk);
      // #1;
      penable <= 1;

      @ (posedge pclk);
      // #1;
      enable_gated_pclk <= 0;
      penable <= 0;
      psel    <= 0;
      pwrite  <= 1'd0;
      pwdata  <= 32'bx;
      paddr   <= 8'bx;
    end
  endtask // apb_write


  /*------------------------------------------------------------------
   *
   * apb read.
   *
   * */

  task apb_read;

    // Arguments:
    input [31:0] address;
    output [31:0] data;

    begin
      // assume we have been called on or soon after the rising edf of pclk.
      // #1;
      enable_gated_pclk <= 1;
      penable <= 0;
      psel    <= 1;
      pwrite  <= 1'd0;
      paddr   <= address[9:2];

      @ (posedge pclk);
      // #1;
      penable <= 1;

      @ (posedge pclk);
      // #1;
      data    = prdata;
      enable_gated_pclk <= 0;
      penable <= 0;
      psel    <= 0;
      pwrite  <= 1'd0;
      paddr   <= 8'bx;

`ifdef DEBUG
      $display("APB read of addr: %x, data: %x : %m", address, data);
`endif
    end
  endtask // apb_write


  /*------------------------------------------------------------------
   *
   *
   *
   * */


  //---------------------------------------------------------------------
  // Local Variables:
  // verilog-library-directories:("." "..")
  // verilog-library-extensions:(".v")
  // End:

